package org.midy.server;

import org.midy.infrastructure.ClientInformationDistribution;
import org.midy.infrastructure.ConsoleInputThread;
import org.midy.infrastructure.IOEventDrivenContainer;
import org.midy.infrastructure.config.SysConfig;
import org.midy.infrastructure.tools.Logger;
import org.midy.infrastructure.tools.ThreadTools;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 全双工的客户端
 */
public class ClientMain2 {
    public static void main(String[] args) {
        /* 系统参数配置 */
        SysConfig.modeServer = false; // 客户端模式
        SysConfig.printDevLog = false; // 打印后台日志

        final AtomicBoolean notify = new AtomicBoolean(true);
        String serverIp = "10.252.16.219";
        int serverPort = 5058;
        int timeout = 10;
        /* 业务处理派发实现类 */
        ClientInformationDistribution defaultInformationDistribution = new ClientInformationDistribution();
        /* 初始化一个循环事件组，用来处理IO事件监听 */
        IOEventDrivenContainer ioStreamContainer = new IOEventDrivenContainer("ReadWriteContainer", 1, defaultInformationDistribution, null);
        /* 初始化一个循环事件组，用来处理连接事件，需要关联到另外一个循环事件组 */
        SocketChannel socketChannel = connetServer(serverIp, serverPort, timeout);
        Logger.info("连接到服务器[%s:%d]成功", serverIp, serverPort);
        /* 注册读事件 */
        ioStreamContainer.allocation(socketChannel, SelectionKey.OP_READ);
        /* 支持控制台消息的发送 */
        ConsoleInputThread.startConsoleInputThread(socketChannel, ioStreamContainer);
        ThreadTools.hold(notify);
    }

    public static SocketChannel connetServer(String ip, int port, int timeout) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.socket().setKeepAlive(true);
            boolean connect = socketChannel.connect(new InetSocketAddress(ip, port));
            if(connect) {
                return socketChannel;
            }
            long expectTimeout = System.currentTimeMillis() + (timeout * 1000);
            while (expectTimeout >= System.currentTimeMillis()) {
                if(socketChannel.isConnected() || socketChannel.finishConnect()) {
                    return socketChannel;
                } else if(socketChannel.isConnectionPending()) {
                    ThreadTools.sleep(500);
                } else {
                    break;
                }
            }
            throw new RuntimeException("连接服务器超时");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
